import pygame, sys, random

# Initialize pygame
pygame.init()
pygame.mixer.init()

# Setup pygame screen size
screen = pygame.display.set_mode((576, 960))

# Set game Frame Per Second
clock = pygame.time.Clock()

# Surfaces
bg_surface = pygame.image.load("assets/background-day.png").convert()
bg_surface = pygame.transform.scale2x(bg_surface)

game_over_surface = pygame.image.load("assets/message.png").convert_alpha()
game_over_surface = pygame.transform.scale2x(game_over_surface)
game_over_rect = game_over_surface.get_rect(center = (288, 480))

floor_surface = pygame.image.load("assets/base.png").convert()
floor_surface = pygame.transform.scale2x(floor_surface)

bird_downflap = pygame.image.load("assets/bluebird-downflap.png").convert()
bird_downflap = pygame.transform.scale2x(bird_downflap)
bird_midflap = pygame.image.load("assets/bluebird-midflap.png").convert()
bird_midflap = pygame.transform.scale2x(bird_midflap)
bird_upflap = pygame.image.load("assets/bluebird-upflap.png").convert()
bird_upflap = pygame.transform.scale2x(bird_upflap)

bird_frames = [bird_downflap, bird_midflap, bird_upflap]
bird_index = 0

bird_surface = bird_frames[bird_index]
bird_rect = bird_surface.get_rect(center = (100, 400))

pipe_surface = pygame.image.load("assets/pipe-green.png").convert()
pipe_surface = pygame.transform.scale2x(pipe_surface)

pipe_list = [] # 保存所有生成出来的水管
pipe_height = [350, 400, 450, 500]

floor_x_pos = 0
bg_x_pos = 0

gravity = 0.25 # 鸟自身的重力，越大掉的越快
fall = 0       # 鸟在垂直方向移动的距离

# 如何能让水管源源不断地从屏幕右侧出现
# 时间事件的名称
SPAWNPIPE = pygame.USEREVENT
pygame.time.set_timer(SPAWNPIPE, 1500) # 每 1500 毫秒向程序发送一次 SPAWNPIPE

# 控制鸟扇翅膀的时间
BIRDFLAP = pygame.USEREVENT + 1
pygame.time.set_timer(BIRDFLAP, 200)

game_active = True

flap_sound = pygame.mixer.Sound("sound/sfx_wing.wav")
game_over_sound = pygame.mixer.Sound("sound/sfx_hit.wav")
score_sound = pygame.mixer.Sound("sound/sfx_point.wav")

score = 0

game_font = pygame.font.Font("fonts/04B_19.TTF", 40)

# functions
def draw_backgrounds():
  screen.blit(bg_surface, (bg_x_pos, 0))
  screen.blit(bg_surface, (bg_x_pos + 576, 0))

def draw_floors():
  screen.blit(floor_surface, (floor_x_pos, 800)) # 屏幕内的地板
  # 屏幕外右侧的地板
  screen.blit(floor_surface, (floor_x_pos + 576, 800))

def create_pipes():
  random_pipe_y = random.choice(pipe_height)
  top_pipe = pipe_surface.get_rect(midbottom = (700, random_pipe_y - 300))
  bottom_pipe = pipe_surface.get_rect(midtop = (700, random_pipe_y))

  return top_pipe, bottom_pipe

def move_pipes(pipes):
  for pipe in pipes:
    pipe.centerx -= 5

  return pipes

def draw_pipes(pipes):
  for pipe in pipes:
    if pipe.bottom < 960:
      # 上面的水管
      # 水管翻过来再显示
      flip_pipe_surface = pygame.transform.flip(pipe_surface, False, True)
      screen.blit(flip_pipe_surface, pipe)
    else:
      screen.blit(pipe_surface, pipe)

def check_collsion(pipes):
  # 水管碰撞
  for pipe in pipes:
    if bird_rect.colliderect(pipe):
      game_over_sound.play()
      return True
  
  # 判断出界
  if bird_rect.top <= -100 or bird_rect.bottom >= 800:
    game_over_sound.play()
    return True

  return False

# bird 原始的 surface
def rorate_bird(bird):
  return pygame.transform.rotozoom(bird, -fall * 2, 1)

def bird_animation():
  new_bird = bird_frames[bird_index]
  new_bird_rect = new_bird.get_rect(center = (100, bird_rect.centery))

  return new_bird, new_bird_rect

def score_display():
  score_surface = game_font.render(str(int(score)), True, (255, 255, 255))
  score_rect = score_surface.get_rect(center = (288, 100))

  screen.blit(score_surface, score_rect)

countdown = 50

# Event loop
while True: # 游戏的执行过程
  # event list
  for event in pygame.event.get():
    if event.type == pygame.QUIT:
      pygame.quit()
      sys.exit() # 告诉操作系统程序正常结束

    if event.type == pygame.KEYDOWN:
      if event.key == pygame.K_SPACE and game_active:
        fall = 0
        fall -= 10

        flap_sound.play()
      if event.key == pygame.K_SPACE and game_active == False:
        # 重启游戏
        # 清空所有水管
        pipe_list.clear()
        
        # 鸟回归到初始位置
        fall = 0
        score = 0

        bird_rect.center = (100, 400)
        game_active = True

    if event.type == SPAWNPIPE:
      # 我们要创建水管了
      pipe_list.extend(create_pipes())

    if event.type == BIRDFLAP:
      # 切换鸟的造型
      bird_index += 1

      if bird_index >= 3:
        bird_index = 0

      # 根据 bird_index 的值选择不同的鸟的 surface
      bird_surface, bird_rect = bird_animation()
    

  # background
  bg_x_pos -= 0.6
  draw_backgrounds()
  if bg_x_pos <= -576:
    bg_x_pos = 0 


  if game_active:
    # bird
    # 1. fall down
    # 2. fly up by pressing the space button
    fall += gravity
    bird_rect.centery += fall

    r_bird_surface = rorate_bird(bird_surface)
    screen.blit(r_bird_surface, bird_rect)

    # pipes
    pipe_list = move_pipes(pipe_list)
    draw_pipes(pipe_list)

    game_active = not check_collsion(pipe_list)

    # 最简单的一个计分规则
    # 鸟活着就不停计分
    score += 0.02
    countdown -= 1

    if countdown <= 0:
      score_sound.play()
      countdown = 50

  else:
    screen.blit(game_over_surface, game_over_rect)

  score_display()
  
  # floor
  floor_x_pos -= 2
  draw_floors()
  if floor_x_pos <= -576:
    floor_x_pos = 0

  pygame.display.update() # Update game screen
  clock.tick(120) # 30, 60, 120, 144
